package com.gxljc.bear.crawler.weixin;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.gxljc.commons.core.RedisUtils;
import com.gxljc.commons.redis.dao.Basegxljcedis;
import com.gxljc.commons.util.Pair;
import com.gxljc.bear.crawler.base.DolphinCrawlerConsts;
import com.gxljc.bear.crawler.base.DolphinFetchData;
import com.gxljc.bear.crawler.image.ImageFresh;
import com.gxljc.bear.crawler.util.HtmlUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 搜狗微信账号数据爬虫。
 *
 * @author tanghaitao
 * @since 2022-8-1
 */
public class SogouPageSeedCrawler implements Serializable {
    public static Logger LOG = Logger.getLogger(SogouPageSeedCrawler.class);
    private Boolean proxy = false;
    private Boolean updateAll = false;

    public SogouPageSeedCrawler(Boolean proxy, Boolean updateAll) {
        this.updateAll = updateAll;
        this.proxy = proxy;
    }

    //单条url入口
    public int crawl(AccountTable table) throws Exception {
        String url = table.crawlUrl;
        LOG.info("crawl = " + url);
        String cookie = weixinCookie();
        System.out.println("cookie =" + cookie);
        String firstUrl = String.format(WeixinConst.SEARCH_URL, table.accountId);
        DolphinFetchData fetchData = DolphinFetchData.getInstance(DolphinCrawlerConsts.CrawlerChannelType.MOVIE.getName());
        byte[] htmlByte = fetchData.getWeixinHtml(url, firstUrl, proxy, WeixinConst.CRAWL_TIMEOUT, cookie);
        if (htmlByte == null) {
            LOG.error("page result is empty url = " + url);
            return DolphinCrawlerConsts.RESULT_NO;
        }
        String html = new String(htmlByte);
        if (StringUtils.isEmpty(html)) {
            LOG.error("page result is empty url = " + url);
            return DolphinCrawlerConsts.RESULT_NO;
        }
//        String html = fetchData.getProxyServer2Result(url,"utf-8",WeixinConst.CRAWL_TIMEOUT);
        if (html.contains(">验证码有误<")) {
            LOG.error("crawl error " + url + " id = " + table.accountId);
            return DolphinCrawlerConsts.RESULT_NO;
        }
        int flag = extractAccount(table, html);
        if (flag == DolphinCrawlerConsts.RESULT_NO) {
            LOG.error("account is empty = " + url);
            return DolphinCrawlerConsts.RESULT_NO;
        }
        WeixinMongodbUtil.saveMongodbAccount(table, WeixinConst.MONGODB_TABLE_ACCOUNT);
        List<PageTable> pages = extractPage(table, html);
        WeixinMongodbUtil.savePageMongodb(pages, WeixinConst.MONGODB_SOGOU_PAGE);
        return DolphinCrawlerConsts.RESULT_YES;
    }


    //主体
    private void extractMainBody(AccountTable table, Document doc) {
        Elements mainBodyElement = doc.select(".profile_desc_value");
        if (CollectionUtils.isEmpty(mainBodyElement)) return;
        String mainBody = mainBodyElement.get(1).text();
        if (StringUtils.isEmpty(mainBody)) return;
        mainBody = mainBody.replaceAll("&nbps;", "").replaceAll(" ", "").trim();
        table.setMainBody(mainBody);
    }

    //功能介绍
    private void extractDesc(AccountTable table, Document doc) {
        Elements descElement = doc.select(".profile_desc_value");
        if (CollectionUtils.isEmpty(descElement)) return;
        String desc = descElement.get(0).text();
        if (StringUtils.isEmpty(desc)) return;
        desc = desc.replaceAll("&nbps;", "").replaceAll(" ", "").trim();
        table.setDesc(desc);
    }

    //抽取账号名称
    private void extractAccountName(AccountTable table, Document doc) {
        Elements nameElement = doc.select(".profile_nickname");
        if (CollectionUtils.isEmpty(nameElement)) return;
        String name = nameElement.html();
        table.setName(name);
    }

    //页面抽取并返回  object
    private int extractAccount(AccountTable table, String html) throws Exception {
        Document doc = Jsoup.parse(html);
        extractAccountName(table, doc);
        if (StringUtils.isEmpty(table.name)) return DolphinCrawlerConsts.RESULT_NO;
        extractDesc(table, doc);
        parseQRcode(table);
        extractBiz(table, html);
        extractMainBody(table, doc);
        return DolphinCrawlerConsts.RESULT_YES;
    }

    //biz抽取
    private void extractBiz(AccountTable table, String html){
        Pattern pattern = Pattern.compile("var biz = \"(.*?)\"[ ]?\\|\\|");
        Matcher m = pattern.matcher(html);
        if (m.find()) {
            String biz = m.group(1);
            table.setBiz(biz);
        }
    }

    //生成二维码
    private void parseQRcode(AccountTable table) {
        String url = String.format(WeixinConst.WEIXIN_QR_URL, table.accountId);
        table.setQrCode(url);
        ImageFresh fresh = ImageFresh.getInstance();
        Pair<Integer, String> newPicPair = null;
        try {
            newPicPair = fresh.freshOne(url);
            String newPic = newPicPair.second;
            if (!url.equals(newPic))
                table.setQrCode(newPic);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //页面抽取并返回  object
    private List<PageTable> extractPage(AccountTable accountTable, String html) throws Exception {
        final Gson GSON = new Gson();
        String js = extractPageJs(html);
        System.out.println(js);
        if (StringUtils.isEmpty(js)) return null;
        Map<String, Object> map = GSON.fromJson(js, new TypeToken<Map<String, Object>>() {
        }.getType());
        return extractPageJs(accountTable, map);
    }

    //抽取js 转换为PageTable 对象
    private List<PageTable> extractPageJs(AccountTable accountTable, Map<String, Object> map) {
        if (map == null || map.isEmpty()) return null;
        System.out.println(map);
        List list = (List) map.get("list");
        if (CollectionUtils.isEmpty(list)) return null;
        List<PageTable> pageList = new LinkedList<PageTable>();
        for (Object one : list) {
            Map msgInfo = (Map) ((Map) one).get("comm_msg_info");
            if (msgInfo == null || msgInfo.isEmpty()) continue;
            Map extInfo = (Map) ((Map) one).get("app_msg_ext_info");
            if (extInfo == null || extInfo.isEmpty()) continue;
            PageTable table = genTableFromPage(accountTable, extInfo, msgInfo);
            if (table == null) continue;
            pageList.add(table);
            Object itemListObj = extInfo.get("multi_app_msg_item_list");
            if (itemListObj == null) continue;
            List itemList = (List) itemListObj;
            for (Object item : itemList) {
                Map itemInfo = (Map) item;
                PageTable itemTable = genTableFromPage(accountTable, itemInfo , msgInfo);
                if (itemTable == null) continue;
                pageList.add(itemTable);
            }
        }
        return pageList;
    }

    //生成pageTable
    private PageTable genTableFromPage(AccountTable accountTable, Map extInfo, Map msgInfo) {
        PageTable table = new PageTable();
        Object id = msgInfo.get("id");
        Object fakeId = msgInfo.get("fakeid");
        Object fileId = extInfo.get("fileid");
        if (id == null) return null;
        String pageId = ((Double) id).intValue() + "-" + fakeId + "-" + ((Double) fileId).intValue();
        String title = (String) extInfo.get("title");
        String digest = (String) extInfo.get("digest");
        String contentUrl = (String) extInfo.get("content_url");
        String cover = (String) extInfo.get("cover");
        if (StringUtils.isEmpty(contentUrl) || StringUtils.isEmpty(title)) return null;
        String contentUrlStr = HtmlUtil.pictureUrlPref(contentUrl, WeixinConst.WEIXIN_QQ_DOMAIN);
        table.setCrawlUrl(contentUrlStr);
        table.setCover(genCover(cover));
        table.setPageId(pageId);
        table.setTitle(title);
        table.setSummary(digest);
        if (updateAll) table.setCrawlFlag(0); //更新所有文章，默认为不更新
        table.setAccountId(accountTable.accountId);
        table.setAccountName(accountTable.name);
        return table;
    }

    private String genCover(String cover) {
        if (StringUtils.isEmpty(cover)) return null;
        ImageFresh fresh = ImageFresh.getInstance();
        Pair<Integer, String> newPicPair = null;
        try {
            newPicPair = fresh.freshOne(cover);
            String newPic = newPicPair.second;
            if (!cover.equals(newPic))
                return newPic;
            return cover;
        } catch (Exception e) {
            e.printStackTrace();
            return cover;
        }
    }

    //抽取电影获奖信息列表
    private String extractPageJs(String html) {
//        String startStr = "msgList = '";
//        String end = "';";
//        if (html.indexOf(startStr) < 0 || html.indexOf(end) < 0) {
//            return null;
//        }
//        int first = html.indexOf(startStr) + startStr.length();
//        String json = html.substring(first, html.indexOf(end, first));
//        if (StringUtils.isEmpty(json)) return null;
        Pattern pattern = Pattern.compile("msgList =[']?(.*?\\})[']?;");
        Matcher m = pattern.matcher(html);
        if (m.find()) {
            String json = m.group(1);
            return json.replaceAll("&quot;", "\"").replaceAll("&amp;amp;", "&").replace("\\\\/", "/").replace("&nbsp;", " ").replaceAll("&amp;", "&");
        }else{
            return null;
        }



    }

    private String weixinCookie() {
        Basegxljcedis redisDao = RedisUtils.getgxljcedisInstance();
        try {
            return redisDao.get(DolphinCrawlerConsts.cookieAccount.WEIXIN.getName());
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

}
